import {TokenPrice} from '../types/token';
import {
  createContext,
  ReactNode,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react';
import {useSolanaOwnerTokenAccountsProvider} from './useSolana/useSolanaOwnerTokenAccounts';
import {useAccountProvider} from './useAccountProvider';
import {useSolanaClientProvider} from './useSolana/useSolanaClientProvider';
import {useSolanaTokenListProvider} from './useSolana/useSolanaTokenListProvider';
import {coinPriceQuery} from '../api/backend';

type TokenPriceContextType = {
  priceLoading: boolean;
  tokenPrices: TokenPrice[];
  getTokenPrice: (
    tokenSymbol: string,
    tokenAddress?: string,
  ) => Promise<TokenPrice>;
  refreshTokenPrices: () => void;
};

const TokenPriceContext = createContext<TokenPriceContextType | undefined>(
  undefined,
);

export const useTokenPriceProvider = (): TokenPriceContextType => {
  const context = useContext(TokenPriceContext);
  if (!context) {
    throw new Error(
      'useTokenPriceProvider must be used within an TokenPriceProvider',
    );
  }
  return context;
};

export function TokenPriceProvider({
  children,
}: Readonly<{
  children: ReactNode;
}>) {
  const {userTokens, getTokenAccounts, accountsloading} =
    useSolanaOwnerTokenAccountsProvider();
  const {userInfo} = useAccountProvider();
  const {solanaClient} = useSolanaClientProvider();
  const {solanaTokenList} = useSolanaTokenListProvider();
  const [tokenPrices, setTokenPrices] = useState<TokenPrice[]>([]);
  const [priceLoading, setPriceLoading] = useState<boolean>(true);

  const getTokenPrice = async (tokenSymbol: string, tokenAddress?: string) => {
    const tokenPrices = await coinPriceQuery(tokenSymbol);
    if (tokenPrices.length > 0) {
      return tokenPrices[0];
    } else {
      return {
        symbol: tokenSymbol,
        price: '0',
      };
    }
  };
  const refreshTokenPrices = useCallback(() => {
    if (userInfo !== undefined && solanaClient !== undefined) {
      getTokenAccounts();
    }
  }, [userInfo, solanaClient, solanaTokenList, getTokenAccounts]);

  useEffect(() => {
    let interval: NodeJS.Timeout;
    if (userInfo !== undefined && solanaClient !== undefined) {
      getTokenAccounts();
      interval = setInterval(() => {
        console.log('token price refresh....');
        getTokenAccounts();
      }, 3000 * 60);
    }

    return () => {
      clearInterval(interval);
    };
  }, [userInfo, solanaClient, solanaTokenList, getTokenAccounts]);

  useEffect(() => {
    const getTokenPrices = async () => {
      setPriceLoading(true);
      const tokenList = userTokens.map(item => {
        return item.symbol;
      });
      const _tokenPrices = await coinPriceQuery(tokenList.join(','));
      if (_tokenPrices.length > 0) {
        setTokenPrices(_tokenPrices);
      }

      setPriceLoading(false);
    };
    if (!accountsloading && userTokens.length > 0) {
      getTokenPrices();
    }
  }, [accountsloading, userTokens]);

  const contextValue = useMemo(
    () => ({
      priceLoading,
      tokenPrices,
      getTokenPrice,
      refreshTokenPrices,
    }),
    [priceLoading, tokenPrices, getTokenPrice, refreshTokenPrices],
  );

  return (
    <TokenPriceContext.Provider value={contextValue}>
      {children}
    </TokenPriceContext.Provider>
  );
}
